package com.smarttiger.zero.admin.controller;

import com.smarttiger.zero.admin.entity.*;
import com.smarttiger.zero.admin.service.InterfaceService;
import com.smarttiger.zero.admin.service.LogsService;
import com.smarttiger.zero.admin.service.UsersService;
import com.smarttiger.zero.admin.util.ApiMessage;
import com.smarttiger.zero.admin.util.Constant;
import com.smarttiger.zero.admin.webservice.TransferUtil;
import com.smarttiger.zero.logic.ExecuteLogics;
import com.smarttiger.zero.logic.InterfaceContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;

@RestController
@RequestMapping(value = "/zero-admin")
public class ApiController {

    @Autowired
    LogsService logsService;

    @Autowired
    UsersService usersService;

    @Autowired
    private InterfaceService interfaceService;

    @RequestMapping(value = "/ZERO/{code}/{token}", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public Object selectInterfacePostJSON(
            @PathVariable String code,
            @PathVariable String token,
            @RequestBody(required = false) Map<String, Object> paramMap,
            HttpServletRequest request,
            HttpServletResponse response
    ) {
        InterfaceModel interfaceConfig = interfaceService.findByCode(code);
        if(interfaceConfig == null){
            ApiMessage message = new ApiMessage();
            message.setCode("-1");
            message.setData("code不存在");
            return message;
        }
        if (interfaceConfig.getReturnType().equals("xml")) {
            try {
                request.getRequestDispatcher("/ZERO/" + code + "/" + token + "/XML").forward(request, response);
            } catch (ServletException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }
        return excuteGet(interfaceConfig, code, token, request, response, paramMap==null?new HashMap<String, Object>():paramMap);
    }

    @RequestMapping(value = "/ZERO/{code}/{token}/XML", method = RequestMethod.POST, produces = MediaType.APPLICATION_XML_VALUE)
    public Object selectInterfacePostXML(
            @PathVariable String code,
            @PathVariable String token,
            @RequestBody(required = false) Map<String, Object> paramMap,
            HttpServletRequest request,
            HttpServletResponse response
    ) {
        InterfaceModel interfaceConfig = interfaceService.findByCode(code);
        return excuteGet(interfaceConfig, code, token, request, response, paramMap==null?new HashMap<String, Object>():paramMap);
    }

    @RequestMapping(value = "/ZERO/{code}/{token}/XML", method = RequestMethod.GET, produces = MediaType.APPLICATION_XML_VALUE)
    public Object selectInterfaceGetXML(@PathVariable String code,
                                        @PathVariable String token,
                                        HttpServletRequest request,
                                        HttpServletResponse response
    ) {

        InterfaceModel interfaceConfig = interfaceService.findByCode(code);
        return excuteGet(interfaceConfig, code, token, request, response, null);
    }

    @RequestMapping(value = "/ZERO/{code}/{token}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public Object selectInterfaceGetJSON(@PathVariable String code,
                                         @PathVariable String token,
                                         HttpServletRequest request,
                                         HttpServletResponse response
    ) {
        InterfaceModel interfaceConfig = interfaceService.findByCode(code);
        if(interfaceConfig == null){
            ApiMessage message = new ApiMessage();
            message.setCode("-1");
            message.setData("code不存在");
            return message;
        }
        if (interfaceConfig.getReturnType().equals("xml")) {
            try {
                request.getRequestDispatcher("/ZERO/" + code + "/" + token + "/XML").forward(request, response);
            } catch (ServletException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }
        return excuteGet(interfaceConfig, code, token, request, response, null);
    }

    public ApiMessage excuteGet(InterfaceModel interfaceConfig, String code, String token,
                                HttpServletRequest request,
                                HttpServletResponse response, Map<String, Object> postParamMap) {


        ApiMessage message = new ApiMessage();
        if (interfaceConfig == null) {
            message.setCode("-1");
            message.setData("code不存在");
            return message;
        }
        if ("N".equals(interfaceConfig.getIsAlive())) {
            message.setCode("-1");
            message.setData("接口状态为不可用");
            return message;
        }
        UsersModel users = usersService.findByToken(token);
        if (users == null) {
            message.setCode("-1");
            message.setData("token错误");
            return message;
        }

        boolean isBlack = false;
        List<UsersModel> blacklistModels = interfaceConfig.getBlacklistModels();
        for (UsersModel blacklistModel : blacklistModels) {
            if (users.getId().equals(blacklistModel.getId())) {
                isBlack = true;
                break;
            }
        }
        if (isBlack) {
            message.setCode("-1");
            message.setData("接口无权限,请联系管理员！");
            return message;
        }

        boolean isOkUser = false;
        List<UsersGroupModel> usersGroupModels = interfaceConfig.getUsersGroupModels();
        for (UsersGroupModel usersGroupModel : usersGroupModels) {
            List<UsersModel> usersModelList = usersGroupModel.getUsersModelList();
            boolean isHave = false;
            for (UsersModel usersModel : usersModelList) {
                if (users.getId().equals(usersModel.getId())) {
                    isHave = true;
                    break;
                }
            }
            if (isHave) {
                isOkUser = true;
                break;
            }
        }

        if (!isOkUser) {
            boolean isWhite = false;
            List<UsersModel> whitelistModels = interfaceConfig.getWhitelistModels();
            for (UsersModel whitelistModel : whitelistModels) {
                if (users.getId().equals(whitelistModel.getId())) {
                    isOkUser = true;
                    break;
                }
            }
        }

        if (!isOkUser) {
            message.setCode("-1");
            message.setData("接口无权限,请联系管理员。");
            return message;
        }

        Map paramMap = new HashMap();
        if ("GET".equalsIgnoreCase(request.getMethod())) {
            List<InterfaceArgsModel> argsModels = interfaceConfig.getArgsModels();
            for (InterfaceArgsModel argsModel : argsModels) {
                String param = request.getParameter(argsModel.getName());
                //java类型
                if(param != null){
                    paramMap.put(argsModel.getName(), TransferUtil.transferS2J(argsModel.getTypecode(),param));
                }else if (!StringUtils.isEmpty(argsModel.getDefaultValue())) {
                    paramMap.put(argsModel.getName(), TransferUtil.transferS2J(argsModel.getTypecode(),argsModel.getDefaultValue()));
                }else{
                    paramMap.put(argsModel.getName(), null);
                }
            }
        } else if("POST".equalsIgnoreCase(request.getMethod())) {
            List<InterfaceArgsModel> argsModels = interfaceConfig.getArgsModels();
            for (InterfaceArgsModel argsModel : argsModels) {
                Object param = null;
                if(postParamMap.containsKey(argsModel.getName())){
                    param = postParamMap.get(argsModel.getName());
                }else{
                    param = request.getParameter(argsModel.getName());
                }
                //java类型
                if(param != null){
                    paramMap.put(argsModel.getName(), TransferUtil.transferS2J(argsModel.getTypecode(),param.toString()));
                }else if (!StringUtils.isEmpty(argsModel.getDefaultValue())) {
                    paramMap.put(argsModel.getName(), TransferUtil.transferS2J(argsModel.getTypecode(),argsModel.getDefaultValue()));
                }else{
                    paramMap.put(argsModel.getName(), null);
                }
            }
        }else{
            message.setCode("-1");
            message.setData("不支持"+request.getMethod()+"请求");
            return message;
        }

        Map<String, Object> currentValue = InterfaceContext.paramContext.get();
        if (currentValue == null) {
            currentValue = new HashMap<>();
            InterfaceContext.paramContext.set(currentValue);
        }
        currentValue.put(Constant.INTERFACECURRENT, paramMap);


        LogsModel logs = new LogsModel();
        logs.setStartDate(new Date());

        List<LogicModel> logicModels = interfaceConfig.getLogicModels();
        if(logicModels.size()==0){
            message.setCode("-1");
            message.setData("逻辑块没有配置。");
            return message;
        }
        Object o = null;
        try {
            o = ExecuteLogics.executeLogics(logicModels);
            logs.setNote("调用成功");
        } catch (Exception e) {
            e.printStackTrace();
            message.setCode("-1");
            message.setData("逻辑块类配置不正确。");
            logs.setNote("调用失败，请检查逻辑块配置");
            return message;
        } finally {
            logs.setCode(code);
            logs.setName(interfaceConfig.getName());
            logs.setEndDate(new Date());
            logs.setUsersId(users.getId());
            logs.setUsersName(users.getName());
            logsService.save(logs);
        }



        message.setCode("1");
        message.setData(o);
        return message;
    }

}
